using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OnChargeExplosionHoming : OnChargeExplosion
{
	public Vector3 initialPosition;

	public Mortal target;

	public float maxHeight = 20f;

	public float maxFlyDistance;

	public Vector3 lastAliveTargetPosition;

	public int pointsCount = 10;

	private List<Vector3> pathPoints = new List<Vector3>();

	private bool draw;

	public void InvokeBlowUp()
	{
		Invoke("BlowUp", lifeTime);
		startPos = base.transform.position;
	}

	private void CalculatePath()
	{
		if (pathPoints.Count == pointsCount)
		{
			return;
		}
		pathPoints = new List<Vector3>();
		float num = Vector3.Distance(target.GetPositionForChargeHit(), initialPosition);
		float num2 = Mathf.Clamp01(Mathf.Pow(num / maxFlyDistance, 2f)) * maxHeight;
		float num3 = 4f * num2 / (num * num);
		Vector3 normalized = (target.GetPositionForChargeHit() - initialPosition).normalized;
		float num4 = num / (float)pointsCount;
		int num5 = pointsCount;
		int num6 = num5 / 2;
		for (int i = 1; i < num5 + 1; i++)
		{
			int num7 = 0;
			if (i < num6)
			{
				num7 = num6 - i;
			}
			else if (i > num6)
			{
				num7 = i - num6;
			}
			float num8 = Mathf.Pow(Vector3.Distance(initialPosition, initialPosition + normalized * num4 * num7), 2f) * num3;
			Vector3 item = initialPosition + normalized * num4 * i + Vector3.up * (num2 - num8);
			pathPoints.Add(item);
		}
		pathPoints[pointsCount - 1] = target.GetPositionForChargeHit();
	}

	private void UpdatePath()
	{
		if (pathPoints.Count != pointsCount)
		{
			return;
		}
		float num = Vector3.Distance(target.GetPositionForChargeHit(), initialPosition);
		float num2 = Mathf.Clamp01(Mathf.Pow(num / maxFlyDistance, 2f)) * maxHeight;
		float num3 = 4f * num2 / (num * num);
		Vector3 normalized = (target.GetPositionForChargeHit() - initialPosition).normalized;
		float num4 = num / (float)pointsCount;
		int num5 = pointsCount;
		int num6 = num5 / 2;
		for (int i = 1; i < num5 + 1; i++)
		{
			int num7 = 0;
			if (i < num6)
			{
				num7 = num6 - i;
			}
			else if (i > num6)
			{
				num7 = i - num6;
			}
			float num8 = Mathf.Pow(Vector3.Distance(initialPosition, initialPosition + normalized * num4 * num7), 2f) * num3;
			Vector3 value = initialPosition + normalized * num4 * i + Vector3.up * (num2 - num8);
			pathPoints[i - 1] = value;
		}
		pathPoints[pointsCount - 1] = target.GetPositionForChargeHit();
	}

	public override IEnumerator UpdateCharge()
	{
		CalculatePath();
		int i = 0;
		while (!(target == null) && !target.isDead)
		{
			if (base.transform.position.AlmostEquals(pathPoints[i], 0.1f))
			{
				i++;
				if (pathPoints.Count / 2 < i)
				{
					i = pathPoints.Count - 1;
				}
			}
			lastAliveTargetPosition = target.GetPositionForChargeHit();
			base.transform.position = Vector3.MoveTowards(base.transform.position, pathPoints[i], speed * Time.unscaledDeltaTime);
			yield return null;
			if (target == null || target.isDead)
			{
				break;
			}
			UpdatePath();
		}
		while (target != null)
		{
			base.transform.position = Vector3.MoveTowards(base.transform.position, lastAliveTargetPosition, speed * Time.unscaledDeltaTime);
			yield return null;
		}
		BlowUp();
	}

	public override void OnTriggerEnter(Collider other)
	{
		if (!objCollider.isTrigger || !base.isMine)
		{
			return;
		}
		RaycastHit hitInfo = default(RaycastHit);
		Mortal componentInParent = other.gameObject.GetComponentInParent<Mortal>();
		if (componentInParent == null)
		{
			return;
		}
		bool flag = Physics.Linecast(base.transform.position, componentInParent.GetPositionForChargeHit() + Vector3.up * 0.1f, out hitInfo, layer) || Physics.Linecast(base.transform.position, componentInParent.GetPositionForChargeHit() + Vector3.up, out hitInfo, layer) || Physics.Linecast(base.transform.position, componentInParent.GetPositionForChargeHit() + Vector3.up * 3.8f, out hitInfo, layer);
		bool flag2 = other.bounds.Contains(base.transform.position);
		if (!damaged.Contains(componentInParent) && (Vector3.Distance(base.transform.position, componentInParent.GetPositionForChargeHit()) <= 1f || flag || flag2) && (!(componentInParent is PlayerBehavior) || (!(componentInParent as PlayerBehavior).inCar && !(componentInParent as PlayerBehavior).inHelic)))
		{
			SendDamage(componentInParent, Mathf.Clamp(damage * (1f - hitInfo.distance / explosionRadius) + damage * 0.1f, damage * 0.1f, damage), hitInfo.point);
			damaged.Add(componentInParent);
			if (componentInParent is PlayerBehavior && addRepForDamage && base.ownerId == PlayerBehavior.MyPlayer.ownerId && componentInParent != PlayerBehavior.MyPlayer)
			{
				SessionReputationManager.Instance.AddReputation(1f);
			}
		}
	}

	public override void OnCollisionEnter(Collision collision)
	{
		if ((!(objCollider != null) || !objCollider.isTrigger) && base.isMine && (immediatelyExplosionOnCollision || (collision.gameObject.GetComponentInParent<Mortal>() != null && immidiateDestroyIfMortall)))
		{
			rigid.velocity = Vector3.zero;
			rigid.isKinematic = true;
			StopAllCoroutines();
			BlowUp();
		}
	}
}
